package com.cooksys.film_rental.dao.impl;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.cooksys.film_rental.dao.ActorDao;
import com.cooksys.film_rental.model.Actor;
import com.cooksys.film_rental.model.Category;
import com.cooksys.film_rental.model.Film;
import com.cooksys.film_rental.model.FilmActor;

@Repository("ActorDao")
@Transactional
public class ActorDaoImpl implements ActorDao {

	@Autowired(required = true)
	private SessionFactory sessionFactory;

	/**
	 * 
	 * @return the current session from the internal {@link SessionFactory}
	 */
	public Session currentSession() {
		return sessionFactory.getCurrentSession();
	}

	@Override
	public Actor getActorByActorId(Short actorId) {
		Session session = currentSession();

		// returns a record from the ACTOR table as an Actor object based on the
		// given actorId, the table's primary key
		String hql = "from Actor a where a.actorId = :actorId";
		Query query = session.createQuery(hql);
		query.setShort("actorId", actorId);

		@SuppressWarnings("rawtypes")
		List results = query.list();
		if (results.size() == 0) {
			return null;
		}
		return (Actor) results.get(0);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Actor> searchActorsByPartialName(String partialName) {
		Session session = currentSession();

		// split the search string into search terms
		String[] nameFragments = partialName.split("\\s");

		// 'select' statement of the hql query
		String hql = "from Actor a where ";

		// generating the where clause
		for (int i = 0; i < nameFragments.length; i++) {

			// for each search term, add a segment of the where clause that
			// checks both the first_name and last_name columns of the ACTOR
			// table for matches
			hql += "a.firstName like :nameFragment" + i
					+ " or a.lastName like :nameFragment" + i;

			if (i < nameFragments.length - 1) {

				// concatenate these where clause segments with an 'or' operator
				hql += " or ";

			}

		}

		Query query = session.createQuery(hql);

		for (int i = 0; i < nameFragments.length; i++) {

			// parameterize the query with the search terms
			query.setString("nameFragment" + i, "%" + nameFragments[i] + "%");

		}

		return query.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Actor> searchActorsByFilm(Film film) {
		Session session = currentSession();

		// selects the actor objects associated with a given film object
		String hql = "select f.actor from FilmActor f where f.film = :film";
		Query query = session.createQuery(hql);
		query.setEntity("film", film);

		return query.list();
	}

	@Override
	public Actor getActorByFilmActor(FilmActor filmActor) {
		Session session = currentSession();

		// selects the actor object associated with a given filmActor object
		String hql = "select f.actor from FilmActor f where f = :filmActor";
		Query query = session.createQuery(hql);
		query.setEntity("filmActor", filmActor);

		return (Actor) query.list().get(0);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Actor> getAllActors() {
		Session session = currentSession();

		String hql = "from Actor";
		Query query = session.createQuery(hql);

		return query.list();
	}

}
